package ar.com.sudoku.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import ar.com.sudoku.exceptions.InvalidSudokuException;
import ar.com.sudoku.factories.RandomSudokuBuilder;
import ar.com.sudoku.factories.SudokuBuilder;
import ar.com.sudoku.rules.Rule;

public abstract class Sudoku {

	protected Grid grid;
	protected Set<Rule> rules;
	
	public boolean validate() {
		for (Rule rule : rules) {
			if (!rule.apply(grid)) {
				return false;
			}
		}
		return true;
	}
	
	public abstract Set<Grid> solve() throws InvalidSudokuException;
	
	public Set<Rule> getRules() {
		return rules;
	}

	public void setRules(Set<Rule> rules) {
		this.rules = rules;
	}

	public Grid getGrid() {
		return grid;
	}

	public void setGrid(Grid grid) {
		this.grid = grid;
	}
	
	public static void main(String args[]) {
//        Sudoku sudoku = new ForceBruteSudoku();
//        sudoku.setGrid(new ArrayGrid());
//        SudokuNumber number = SudokuNumber._1;
//        sudoku.getGrid().set(SudokuNumber._3,SudokuNumber._6,number);
//        sudoku.getGrid().set(SudokuNumber._6,SudokuNumber._4,number);
//        number = SudokuNumber._2;
//        sudoku.getGrid().set(SudokuNumber._6,SudokuNumber._3,number);
//        sudoku.getGrid().set(SudokuNumber._9,SudokuNumber._6,number);
//        number = SudokuNumber._3;
//        sudoku.getGrid().set(SudokuNumber._3,SudokuNumber._8,number);
//        sudoku.getGrid().set(SudokuNumber._4,SudokuNumber._2,number);
//        sudoku.getGrid().set(SudokuNumber._5,SudokuNumber._7,number);
//        sudoku.getGrid().set(SudokuNumber._9,SudokuNumber._4,number);
//        number = SudokuNumber._4;
//        sudoku.getGrid().set(SudokuNumber._8,SudokuNumber._2,number);
//        number = SudokuNumber._5;
//        sudoku.getGrid().set(SudokuNumber._6,SudokuNumber._5,number);
//        sudoku.getGrid().set(SudokuNumber._8,SudokuNumber._7,number);
//        number = SudokuNumber._6;
//        sudoku.getGrid().set(SudokuNumber._4,SudokuNumber._4,number);
//        sudoku.getGrid().set(SudokuNumber._8,SudokuNumber._1,number);
//        number = SudokuNumber._7;
//        sudoku.getGrid().set(SudokuNumber._2,SudokuNumber._6,number);
//        sudoku.getGrid().set(SudokuNumber._6,SudokuNumber._7,number);
//        sudoku.getGrid().set(SudokuNumber._8,SudokuNumber._8,number);
//        number = SudokuNumber._8;
//        sudoku.getGrid().set(SudokuNumber._2,SudokuNumber._7,number);
//        sudoku.getGrid().set(SudokuNumber._3,SudokuNumber._3,number);
//        sudoku.getGrid().set(SudokuNumber._4,SudokuNumber._5,number);
//        number = SudokuNumber._9;
//        sudoku.getGrid().set(SudokuNumber._8,SudokuNumber._5,number);
//        Set<Rule> rules = new HashSet<Rule>();
//        rules.add(new ColumnRule());
//        rules.add(new RowRule());
//        rules.add(new SquareRule());
//        sudoku.setRules(rules);
        
        try {
            SudokuBuilder builder = new RandomSudokuBuilder();
            Map<Short,List<Long>> r = new HashMap<Short,List<Long>>();
            for (int x = 1; x <= 2; x++) {
            	for (short cells = 25; cells <= 30; cells++) {
            		System.out.println("iteracion " + x + " cantidad de cuadraditos " + cells);
            		Long time = System.currentTimeMillis();
                    builder.createSudoku(cells);
                    Sudoku sudoku = builder.getSudoku();            		
        			Set<Grid> grids = sudoku.solve();
        			time = System.currentTimeMillis() - time;
        			if (r.get(cells) == null) {
        				r.put(cells,new ArrayList<Long>());
        			}
        			r.get(cells).add(time);
        			
        			for (Grid grid : grids) {
        				int i = 0;
        				for (SudokuNumber n : grid.getValues()) {
        					System.out.print(n);
        					i++;
        					if (i == 9) {
        						System.out.println();
        						i = 0;
        					}
        				}
        			}
            	}

            }
//            for (short cells = 1; cells < 81; cells++) {
//            	List<Long> times = r.get(cells);
//            	System.out.println("AAAAAAAAA " + cells + " AAAAAAAAA");
//            	for (Long time : times) {
//            		System.out.println(cells);
//            		System.out.println(time);
//            	}
//            }

		} catch (InvalidSudokuException e) {
			e.printStackTrace();
		}
	}
	
}
